Skip to main content

Sparkling plot

Javascript cells

Example with sparkles plot

He we will couple Javascript canvas and WL plot function

Download original notebook
.js
const canvas = document.createElement('canvas');
canvas.width = 600;
canvas.height = 400;
const context = canvas.getContext('2d');
const particles = [];

function random (min, max) {
  return Math.random() * (max - min) + min;
}

function convertRange( value, r1, r2 ) { 
    return ( value - r1[ 0 ] ) * ( r2[ 1 ] - r2[ 0 ] ) / ( r1[ 1 ] - r1[ 0 ] ) + r2[ 0 ];
}

let uid = 0;
let data = [];

function animate() {
  if (data.length > 0) {
  for (let j=0; j<3; ++j) {
    const it = Math.floor(random(0, data.length-1));
  
    const particle = {
      x: data[it][0],
      y: data[it][1],
      xvel: random(-1,1),
      yvel: random(-1,1),
      color: `rgba(${random(0, 255)}, ${random(0, 255)}, ${random(0, 255)}, 0.5)`,
      size: 7,
      age: 1
    };
  
    particles.push(particle);
    if (particles.length > 2000) {
      particles.shift();
    }
  }
  }
  
  context.clearRect(0, 0, canvas.width, canvas.height);
  for (let i = 0; i < particles.length; i += 1){
    const p = particles[i];
    context.beginPath();
    context.arc(p.x, p.y, p.size/p.age, 0, Math.PI * 2, true);
    context.fillStyle = p.color;
    context.fill();
    context.closePath(); 
    p.age += 0.1;
    p.x += p.xvel;
    p.y -= p.yvel;  
  }

  uid = window.requestAnimationFrame(animate);
}

this.ondestroy = () => {
  window.cancelAnimationFrame(uid)
}

//function definition 
core.Spark = async (args, env) => {
  //update the positions
  const raw = await interpretate(args[0], env);
  const min = [Math.min.apply(null, raw.map((e) => e[0])), Math.min.apply(null, raw.map((e) => e[1]))];
  const max = [Math.max.apply(null, raw.map((e) => e[0])), Math.max.apply(null, raw.map((e) => e[1]))];

  data = raw.map((e)=>[convertRange(e[0], [min[0], max[0]], [50, 550]), convertRange(e[1], [max[1], min[1]], [50, 350])]);
  
}

//kickstarter
animate();

return canvas;
const canvas = document.createElement('canvas');
canvas.width = 600;
canvas.height = 400;
const context = canvas.getContext('2d');
const particles = [];

function random (min, max) {
  return Math.random() * (max - min) + min;
}

function convertRange( value, r1, r2 ) { 
    return ( value - r1[ 0 ] ) * ( r2[ 1 ] - r2[ 0 ] ) / ( r1[ 1 ] - r1[ 0 ] ) + r2[ 0 ];
}

let uid = 0;
let data = [];

function animate() {
  if (data.length > 0) {
  for (let j=0; j<3; ++j) {
    const it = Math.floor(random(0, data.length-1));
  
    const particle = {
      x: data[it][0],
      y: data[it][1],
      xvel: random(-1,1),
      yvel: random(-1,1),
      color: `rgba(${random(0, 255)}, ${random(0, 255)}, ${random(0, 255)}, 0.5)`,
      size: 7,
      age: 1
    };
  
    particles.push(particle);
    if (particles.length > 2000) {
      particles.shift();
    }
  }
  }
  
  context.clearRect(0, 0, canvas.width, canvas.height);
  for (let i = 0; i < particles.length; i += 1){
    const p = particles[i];
    context.beginPath();
    context.arc(p.x, p.y, p.size/p.age, 0, Math.PI * 2, true);
    context.fillStyle = p.color;
    context.fill();
    context.closePath(); 
    p.age += 0.1;
    p.x += p.xvel;
    p.y -= p.yvel;  
  }

  uid = window.requestAnimationFrame(animate);
}

this.ondestroy = () => {
  window.cancelAnimationFrame(uid)
}

//function definition 
core.Spark = async (args, env) => {
  //update the positions
  const raw = await interpretate(args[0], env);
  const min = [Math.min.apply(null, raw.map((e) => e[0])), Math.min.apply(null, raw.map((e) => e[1]))];
  const max = [Math.max.apply(null, raw.map((e) => e[0])), Math.max.apply(null, raw.map((e) => e[1]))];

  data = raw.map((e)=>[convertRange(e[0], [min[0], max[0]], [50, 550]), convertRange(e[1], [max[1], min[1]], [50, 350])]);
  
}

//kickstarter
animate();

return canvas;

Now a couple of adapters to make it easier

SparkPlot[func_, range_] := With[{var = Extract[range,1, Inactivate], min = range[[2]], max = range[[3]]}, Table[{var, func}, {var, min, max, (max-min)/200.0}]] // FrontSubmit[Spark[#]] &

SetAttributes[SparkPlot, HoldAll]

Click on any button down there

Button["Sinc", SparkPlot[Sinc[x], {x,-10,10}]]
Button["Cos", SparkPlot[Cos[x], {x,-10,10}]]
Button["x", SparkPlot[x, {x,-10,10}]]
(*VB[*)(EventObject[<|"Id" -> "d2a2f570-23bb-4f96-9a24-ac2c630aaa56", "Initial" -> False, "View" -> "67651fbd-9a8b-4f9e-b498-5f83cda30391"|>])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKm5mbmRqmJaXoWiZaJOmapFmm6iaZWFromqZZGCenJBobGFsaAgCIeRW5"*)(*]VB*)
(*VB[*)(EventObject[<|"Id" -> "664aa2f9-546a-4cd5-941e-1da36df42bc1", "Initial" -> False, "View" -> "c030c8fd-1bcd-473e-a387-9f46a1e4d079"|>])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKJxsYGyRbpKXoGiYlp+iamBun6iYaW5jrWqaZmCUappqkGJhbAgCMnRXW"*)(*]VB*)
(*VB[*)(EventObject[<|"Id" -> "4b322b3f-48c9-4c96-9423-c8eeb55eddbd", "Initial" -> False, "View" -> "f63cf7fe-91c7-4b52-95cf-67a91de39074"|>])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKp5kZJ6eZp6XqWhomm+uaJJka6VqaJqfpmpknWhqmpBpbGpibAACNyhW9"*)(*]VB*)